package drds.plus.sql_process.parser.visitor;

import com.google.common.collect.Maps;
import drds.plus.parser.abstract_syntax_tree.expression.BinaryExpression;
import drds.plus.parser.abstract_syntax_tree.expression.Expression;
import drds.plus.parser.abstract_syntax_tree.expression.UnaryExpression;
import drds.plus.parser.abstract_syntax_tree.expression.arithmetic.Add;
import drds.plus.parser.abstract_syntax_tree.expression.arithmetic.Mod;
import drds.plus.parser.abstract_syntax_tree.expression.arithmetic.Subtract;
import drds.plus.parser.abstract_syntax_tree.expression.comparison.Is;
import drds.plus.parser.abstract_syntax_tree.expression.comparison.fuzzy_matching.Like;
import drds.plus.parser.abstract_syntax_tree.expression.comparison.range.*;
import drds.plus.parser.abstract_syntax_tree.expression.logical.And;
import drds.plus.parser.abstract_syntax_tree.expression.logical.ListExpression;
import drds.plus.parser.abstract_syntax_tree.expression.logical.Or;
import drds.plus.parser.abstract_syntax_tree.expression.primary.function.aggregation.*;
import drds.plus.parser.abstract_syntax_tree.expression.primary.literal.LiteralBoolean;
import drds.plus.parser.abstract_syntax_tree.expression.primary.literal.LiteralNull;
import drds.plus.parser.abstract_syntax_tree.expression.primary.literal.LiteralNumber;
import drds.plus.parser.abstract_syntax_tree.expression.primary.literal.LiteralString;
import drds.plus.parser.abstract_syntax_tree.expression.primary.misc.Identifier;
import drds.plus.parser.abstract_syntax_tree.expression.primary.misc.InList;
import drds.plus.parser.abstract_syntax_tree.expression.primary.misc.ParameterMarker;
import drds.plus.parser.abstract_syntax_tree.expression.primary.misc.RowValues;
import drds.plus.parser.abstract_syntax_tree.expression.primary.subquery.AllQuery;
import drds.plus.parser.abstract_syntax_tree.expression.primary.subquery.AnyQuery;
import drds.plus.parser.abstract_syntax_tree.expression.primary.subquery.Exists;
import drds.plus.parser.abstract_syntax_tree.statement.SelectStatement;
import drds.plus.parser.abstract_syntax_tree.statement.UnionStatement;
import drds.plus.parser.abstract_syntax_tree.statement.select.table.*;
import drds.plus.parser.lexer.Lexer;
import drds.plus.parser.parser.ExpressionParser;
import drds.plus.parser.visitor.EmptyVisitor;
import drds.plus.parser.visitor.VisitorImpl;
import drds.plus.sql_process.abstract_syntax_tree.ObjectCreateFactory;
import drds.plus.sql_process.abstract_syntax_tree.expression.NullValue;
import drds.plus.sql_process.abstract_syntax_tree.expression.bind_value.BindValue;
import drds.plus.sql_process.abstract_syntax_tree.expression.bind_value.SequenceValue;
import drds.plus.sql_process.abstract_syntax_tree.expression.item.Item;
import drds.plus.sql_process.abstract_syntax_tree.expression.item.column.Column;
import drds.plus.sql_process.abstract_syntax_tree.expression.item.function.*;
import drds.plus.sql_process.abstract_syntax_tree.node.query.Join;
import drds.plus.sql_process.abstract_syntax_tree.node.query.Query;
import drds.plus.sql_process.abstract_syntax_tree.node.query.TableQuery;
import drds.plus.sql_process.parser.visitor.dml.SelectVisitor;
import drds.tools.$;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;

/**
 * SelectVisitor ExpressionVisitor这两个类缩写sv ev.在这个类允许java缩写实例命名
 */
public class ExpressionVisitor extends EmptyVisitor {

    private static Map emptyMap = Maps.newHashMap();
    private Query parent;
    private Object columnOrValue;
    private Query query = null;
    private String valueForLike;
    private Filter filter;
    private PrecedenceMode precedenceMode = PrecedenceMode.UNDEF;
    private String expressionSqlString = null;

    public ExpressionVisitor() {
        this(null);
    }

    public ExpressionVisitor(Query parent) {
        this.parent = parent;
    }

    public static ExpressionVisitor parser(String condition) {
        if ($.isNullOrEmpty(condition)) {
            return null;
        }
        try {
            ExpressionParser expressionParser = new ExpressionParser(new Lexer(condition));
            Expression expression = expressionParser.expression();
            Class aClass = expression.getClass();
            //
            ExpressionVisitor ev = new ExpressionVisitor(null);
            Method method = null;
            while (true) {
                try {
                    method = ev.getClass().getMethod("visit", aClass);
                } catch (Exception e) {
                    // ignore
                }
                if (method == null) {
                    aClass = aClass.getSuperclass();
                    if (aClass == null) {
                        throw new UnsupportedOperationException("parser failed : " + condition);
                    }
                } else {
                    break;
                }
            }
            method.invoke(ev, expression);
            return ev;
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    public void visit(BetweenAnd betweenAnd) {
        Expression comparee = betweenAnd.getComparee();
        Expression notLessThan = betweenAnd.getNotLessThan();
        Expression notGreaterThan = betweenAnd.getNotGreaterThan();
        //
        ExpressionVisitor cev = new ExpressionVisitor(parent);
        comparee.accept(cev);
        Object cv = cev.getObject();
        //
        ExpressionVisitor lev = new ExpressionVisitor(parent);
        notLessThan.accept(lev);
        Object lv = lev.getObject();
        //
        ExpressionVisitor rev = new ExpressionVisitor(parent);
        notGreaterThan.accept(rev);
        Object rv = rev.getObject();
        //
        LogicalOperationFilter logicalOperationFilter = buildLogicalFilter(betweenAnd, this.buildBooleanFilter(betweenAnd, cv, Operation.greater_than_or_equal, lv), Operation.and, this.buildBooleanFilter(betweenAnd, cv, Operation.less_than_or_equal, rv));
        if (betweenAnd.isNot()) {
            logicalOperationFilter.setIsNot(true);
        }
        this.filter = logicalOperationFilter;
    }

    public void visit(Is is) {
        BooleanFilter booleanFilter = ObjectCreateFactory.createBooleanFilter();
        ExpressionVisitor ev = new ExpressionVisitor(parent);
        is.getExpression().accept(ev);
        booleanFilter.setColumn(ev.getObject());
        if (is.getMode() == Is.IS_NULL) {
            booleanFilter.setOperation(Operation.is_null);
            booleanFilter.setIsNot(false);
        } else if (is.getMode() == Is.IS_NOT_NULL) {
            booleanFilter.setOperation(Operation.is_not_null);
            booleanFilter.setIsNot(false);
        } else if (is.getMode() == Is.IS_FALSE) {
            booleanFilter.setOperation(Operation.is_false);
            booleanFilter.setIsNot(false);
        } else if (is.getMode() == Is.IS_NOT_FALSE) {
            booleanFilter.setOperation(Operation.is_not_false);
            booleanFilter.setIsNot(false);
        } else if (is.getMode() == Is.IS_TRUE) {
            booleanFilter.setOperation(Operation.is_true);
            booleanFilter.setIsNot(false);
        } else if (is.getMode() == Is.IS_NOT_TRUE) {
            booleanFilter.setOperation(Operation.is_not_true);
            booleanFilter.setIsNot(false);
        }
        this.filter = booleanFilter;
    }


    public void visit(BinaryExpression binaryExpression) {
        if (eval(binaryExpression)) { // 计算出了结果
            return;
        }
        if (binaryExpression instanceof Equal) {
            this.handleBooleanFilter(binaryExpression, Operation.equal);
        } else if (binaryExpression instanceof NotEqual) {
            this.handleBooleanFilter(binaryExpression, Operation.not_equal);
        } else if (binaryExpression instanceof LessThan) {
            this.handleBooleanFilter(binaryExpression, Operation.less_than);
        } else if (binaryExpression instanceof LessThanOrEquals) {
            this.handleBooleanFilter(binaryExpression, Operation.less_than_or_equal);
        } else if (binaryExpression instanceof GreaterThan) {
            this.handleBooleanFilter(binaryExpression, Operation.greater_than);
        } else if (binaryExpression instanceof GreaterThanOrEquals) {
            this.handleBooleanFilter(binaryExpression, Operation.greater_than_or_equal);
            //
        } else if (binaryExpression instanceof Add) {
            this.handleArithmetric(binaryExpression, FunctionName.add);
        } else if (binaryExpression instanceof Subtract) {
            this.handleArithmetric(binaryExpression, FunctionName.sub);
        } else if (binaryExpression instanceof Mod) {
            this.handleArithmetric(binaryExpression, FunctionName.mod);
        } else if (binaryExpression instanceof In) {
            this.handleInExpression((In) binaryExpression);
        } else {
            throw new UnsupportedOperationException("not supported this BinaryOperatorExpression type " + binaryExpression.getOperator());
        }
    }

    private void handleBooleanFilter(BinaryExpression binaryOperatorExpression, Operation operation) {
        Object column = null;
        Object value = null;

        ExpressionVisitor lev = new ExpressionVisitor(parent);
        binaryOperatorExpression.getLeft().accept(lev);
        column = lev.getObject();

        ExpressionVisitor rev = new ExpressionVisitor(parent);
        binaryOperatorExpression.getRight().accept(rev);
        value = rev.getObject();
        precedenceMode = rev.precedenceMode;

        if (precedenceMode == PrecedenceMode.ALL) {
            switch (operation) {
                case greater_than:
                    operation = Operation.greater_than_all;
                    break;
                case greater_than_or_equal:
                    operation = Operation.greater_than_or_equal_all;
                    break;
                case equal:
                    operation = Operation.equal_all;
                    break;
                case not_equal:
                    operation = Operation.not_equal_all;
                    break;
                case less_than:
                    operation = Operation.less_than_all;
                    break;
                case less_than_or_equal:
                    operation = Operation.less_than_or_equal_all;
                    break;

                default:
                    break;
            }
        } else if (precedenceMode == PrecedenceMode.ANY) {
            switch (operation) {
                case greater_than:
                    operation = Operation.greater_than_any;
                    break;
                case greater_than_or_equal:
                    operation = Operation.greater_than_or_equal_any;
                    break;
                case equal:
                    operation = Operation.equal_any;
                    break;
                case not_equal:
                    operation = Operation.not_equal_any;
                    break;
                case less_than:
                    operation = Operation.less_than_any;
                    break;
                case less_than_or_equal:
                    operation = Operation.less_than_or_equal_any;
                    break;
                default:
                    break;
            }
        }

        this.filter = buildBooleanFilter(binaryOperatorExpression, column, operation, value);
    }

    private void handleArithmetric(BinaryExpression binaryExpression, String functionName) {
        List<Object> argList = new ArrayList<Object>(2);
        //
        ExpressionVisitor lev = new ExpressionVisitor(parent);
        binaryExpression.getLeft().accept(lev);
        argList.add(lev.getObject());
        //
        ExpressionVisitor rev = new ExpressionVisitor(parent);
        binaryExpression.getRight().accept(rev);
        argList.add(rev.getObject());
        //
        Function function = ObjectCreateFactory.createFunction();
        function.setFunctionName(functionName);
        function.setArgList(argList); // 设置参数
        function.setColumnName(getExpressionSqlString(binaryExpression));
        this.columnOrValue = function;
    }

    public void visit(UnaryExpression unaryExpression) {
        if (eval(unaryExpression)) { // 计算出了结果
            return;
        }

        if (unaryExpression instanceof AllQuery) {
            SelectVisitor sv = new SelectVisitor(parent);
            unaryExpression.getExpression().accept(sv);
            query = sv.getQuery();
            expressionSqlString = getExpressionSqlString(unaryExpression);
            precedenceMode = PrecedenceMode.ALL;
            return;
        } else if (unaryExpression instanceof AnyQuery) {
            SelectVisitor sv = new SelectVisitor(parent);
            unaryExpression.getExpression().accept(sv);
            query = sv.getQuery();
            expressionSqlString = getExpressionSqlString(unaryExpression);
            precedenceMode = PrecedenceMode.ANY;
            return;
        } else {
            // BitInvert
            // CastBinaryExpression
            //
            List argList = new ArrayList(1);
            ExpressionVisitor ev = new ExpressionVisitor(parent);
            unaryExpression.getExpression().accept(ev);
            Object arg = ev.getObject();
            argList.add(arg);
            //
            Function function = ObjectCreateFactory.createFunction();
            function.setFunctionName(unaryExpression.getOperator());
            function.setArgList(argList);
            function.setColumnName(this.getExpressionSqlString(unaryExpression));
            columnOrValue = function;
        }
    }

    public void visit(drds.plus.parser.abstract_syntax_tree.expression.primary.function.Function function) {
        boolean argDistinct = isDistinct(function);
        //
        Function $function = ObjectCreateFactory.createFunction();
        $function.setFunctionName(function.getFunctionName());
        List<Expression> argList = function.getArgList();
        if (argList != null) {
            ArrayList<Object> newArgsList = new ArrayList<Object>();
            for (Expression expression : argList) {
                ExpressionVisitor ev = new ExpressionVisitor(parent);
                expression.accept(ev);
                Object object = ev.getObject();
                if ((object instanceof Item)) {
                    ((Item) object).setDistinct(argDistinct);
                }
                newArgsList.add(ev.getObject());
            }
            $function.setArgList(newArgsList);
        } else {
            $function.setArgList(new ArrayList());
        }
        $function.setColumnName(getExpressionSqlString(function));
        columnOrValue = $function;
    }

    public void visit(RowValues rowValues) {
        Function function = ObjectCreateFactory.createFunction();
        function.setFunctionName(FunctionName.row);
        List<Comparable> argList = new ArrayList<Comparable>();
        for (int i = 0; i < rowValues.getRowValueList().size(); i++) {
            ExpressionVisitor ev = new ExpressionVisitor(parent);
            rowValues.getRowValueList().get(i).accept(ev);
            Object object = ev.getObject();
            argList.add((Comparable) object);
        }
        function.setArgList(argList);
        function.setColumnName(getExpressionSqlString(rowValues));
        columnOrValue = function;
    }

    public void visit(Identifier identifier) {
        String name = identifier.getText();
        if (SequenceValue.SEQ_NEXTVAL.equals(name)) {
            if (identifier.getParent() == null) {
                throw new RuntimeException("SEQUENCE NAME is NOT EMPTY.");
            }
            name = identifier.getParent().getText();
            this.columnOrValue = ObjectCreateFactory.createSequenceValue(name);
        } else {
            Column column = ObjectCreateFactory.createColumn();
            if (identifier.getParent() != null) { // table.column
                column.setTableName(identifier.getParent().getText());
            }
            column.setColumnName(identifier.getText());
            this.columnOrValue = column;
        }
    }

    public void visit(InnerJoin innerJoin) {
        ITable leftTable = innerJoin.getLeftTable();
        ITable rightTable = innerJoin.getRightTable();
        Join joinNode = join(leftTable, rightTable);
        joinNode.setInnerJoin();
        Expression on = innerJoin.getOn();
        if (on != null) {
            ExpressionVisitor ev = new ExpressionVisitor(parent);
            on.accept(ev);
            Filter filter = ev.getFilter();
            addJoinFilter(joinNode, filter);
        }
        this.query = joinNode;
    }


    public void visit(OuterJoin outerJoin) {
        ITable leftTable = outerJoin.getLeftTable();
        ITable rightTable = outerJoin.getRightTable();
        Join joinNode = join(leftTable, rightTable);
        Expression on = outerJoin.getOn();
        if (on != null) {
            if (outerJoin.isLeftJoin()) {
                joinNode.setLeftOuterJoin();
            } else {
                joinNode.setRightOuterJoin();
            }
            ExpressionVisitor ev = new ExpressionVisitor(parent);
            on.accept(ev);
            Filter filter = ev.getFilter();
            addJoinFilter(joinNode, filter);
        }
        this.query = joinNode;
    }


    public void visit(Like like) {
        ExpressionVisitor cev = new ExpressionVisitor(parent);
        like.getComparee().accept(cev);

        ExpressionVisitor pev = new ExpressionVisitor(parent);
        like.getPattern().accept(pev);
        Object value = null;
        if (pev.getValueForLike() != null) {
            value = pev.getValueForLike();
        } else {
            value = pev.getObject();
        }
        this.filter = this.buildBooleanFilter(like, cev.getObject(), Operation.like, value);
        if (like.isNot()) {
            this.filter.setIsNot(true);
        }
    }

    public void visit(LiteralBoolean literalBoolean) {
        this.columnOrValue = literalBoolean.isTrue();
    }

    public void visit(LiteralNull literalNull) {
        this.columnOrValue = NullValue.getNullValue();
    }

    public void visit(LiteralNumber literalNumber) {
        this.columnOrValue = literalNumber.getNumber();
    }

    public void visit(LiteralString literalString) {
        // 由于是绑定变量的形式，普通的操作符要用转义后的，但是like的不行，似乎like比较特殊....
        this.columnOrValue = literalString.getString();
        this.valueForLike = literalString.getString();
    }

    public void visit(ParameterMarker parameterMarker) {
        BindValue bindValue = ObjectCreateFactory.createBindValue(parameterMarker.getParameterIndex());
        columnOrValue = bindValue;
    }

    public void visit(ListExpression listExpression) {
        if (eval(listExpression)) {// 已经计算出了结果
            return;
        }

        Filter rootFilter = null;
        for (int i = 0; i < listExpression.size(); i++) {
            Expression expression = listExpression.getExpression(i);
            ExpressionVisitor ev = new ExpressionVisitor(parent);
            expression.accept(ev);
            if (expression instanceof LiteralBoolean) {
                if ((Boolean) ev.getObject()) {
                    ev.filter = this.buildConstantFilter(1);
                } else {
                    ev.filter = this.buildConstantFilter(0);
                }
            }
            if (ev.getFilter() == null) {
                if (ev.getObject() != null) {
                    // a or b , a封到一个booleanFilter里
                    ev.filter = this.buildBooleanFilter(listExpression, ev.getObject(), Operation.constant, null);
                } else {
                    throw new UnsupportedOperationException("and/or不能没有操作符");
                }
            }
            if (rootFilter == null) {
                rootFilter = ev.getFilter();
            } else {
                if (listExpression instanceof And) {
                    rootFilter = this.buildLogicalFilter(listExpression, rootFilter, Operation.and, ev.getFilter());
                } else if (listExpression instanceof Or) {
                    rootFilter = this.buildLogicalFilter(listExpression, rootFilter, Operation.or, ev.getFilter());
                } else {
                    throw new UnsupportedOperationException(); // 不会到这一步
                }
            }
        }

        this.filter = rootFilter;
    }

    public void visit(SubQuery subQuery) {
        SelectVisitor sv = new SelectVisitor();
        subQuery.accept(sv);
        query = sv.getQuery();
        query.setSubQueryAndSetNeedBuild(true);
        if (subQuery.getAlias() != null) {
            if (query.getAlias() != null) {
                query.setTableSubAliasAndSetNeedBuild(query.getAlias());// 内部子查询的别名
            }
            query.setAliasAndSetNeedBuild(subQuery.getAlias());
        }
    }

    /**
     * @param table
     */
    public void visit(Table table) {
        TableQuery tableQueryNode = new TableQuery(table.getTableName().getText());
        if (table.getAlias() != null) {
            tableQueryNode.setAliasAndSetNeedBuild(table.getAlias());
        }
        this.query = tableQueryNode;
    }


    public void visit(Exists exists) {

        Function function = ObjectCreateFactory.createFunction();
        function.setColumnName(getExpressionSqlString(exists.getQuery()));
        function.setFunctionName(FunctionName.subquery_list);
        //
        SelectVisitor sv = new SelectVisitor(parent);
        exists.getQuery().accept(sv);
        function.getArgList().add(sv.getQuery());
        //
        this.filter = buildBooleanFilter(exists, function, Operation.exists, 1);
    }


    public void visit(SelectStatement selectStatement) {
        SelectVisitor sv = new SelectVisitor(parent);
        selectStatement.accept(sv);
        query = sv.getQuery();
        expressionSqlString = getExpressionSqlString(selectStatement);
    }

    public void visit(UnionStatement unionStatement) {
        throw new UnsupportedOperationException("UnionStatement");
    }


    public BooleanFilter buildBooleanFilter(Expression expression, Object column, Operation operation, Object value) {
        BooleanFilter booleanFilter = ObjectCreateFactory.createBooleanFilter();
        booleanFilter.setColumn(column);
        booleanFilter.setOperation(operation);
        booleanFilter.setValue(value);
        if (expression != null) {
            booleanFilter.setColumnName(getExpressionSqlString(expression)); // 比如将count(*)做为columnName
        }
        return booleanFilter;
    }

    public LogicalOperationFilter buildLogicalFilter(Expression expression, Filter column, Operation operation, Filter value) {
        LogicalOperationFilter logicalOperationFilter = ObjectCreateFactory.createLogicalOperationFilter();
        logicalOperationFilter.addFilter(column);
        logicalOperationFilter.setOperation(operation);
        logicalOperationFilter.addFilter(value);
        if (expression != null) {
            logicalOperationFilter.setColumnName(getExpressionSqlString(expression));
        }
        return logicalOperationFilter;
    }

    public BooleanFilter buildConstantFilter(Object constant) {
        BooleanFilter booleanFilter = ObjectCreateFactory.createBooleanFilter();
        booleanFilter.setOperation(Operation.constant);
        booleanFilter.setColumn(constant);
        booleanFilter.setColumnName(constant.toString());
        return booleanFilter;
    }

    protected boolean eval(Expression expression) {
        // 暂时不做计算，避免列名不一致
        try {
            Object value = expression.eval(emptyMap);
            if (value != null && value != Expression.UNEVALUATABLE) {
                this.expressionSqlString = getExpressionSqlString(expression);
                this.columnOrValue = value;
                return true;
            }
        } catch (Exception e) {
            // ignore
        }
        return false;
    }


    private void handleInExpression(In in) {
        ExpressionVisitor lev = new ExpressionVisitor(parent);
        in.getLeft().accept(lev);
        Object object = lev.getObject();
        //
        BooleanFilter booleanFilter = buildBooleanFilter(in, object, Operation.in, null);
        // 构建values参数
        Expression right = in.getRight();
        if (right instanceof InList) {
            List<Expression> expressionList = ((InList) right).getList();
            List<Object> valueList = new ArrayList<Object>();
            for (Expression expression : expressionList) {
                ExpressionVisitor ev = new ExpressionVisitor(parent);
                expression.accept(ev);
                valueList.add(ev.getObject());
            }
            booleanFilter.setValueList(valueList);
        } else if (right instanceof drds.plus.parser.abstract_syntax_tree.statement.Query) {
            if (right instanceof UnionStatement) {
                throw new UnsupportedOperationException("UnionStatement");
            }

            // 将子查subQuery包装为function
            Function function = ObjectCreateFactory.createFunction();
            function.setColumnName(getExpressionSqlString(right));
            function.setFunctionName(FunctionName.subquery_list);
            //
            SelectVisitor sv = new SelectVisitor(parent);
            right.accept(sv);
            function.getArgList().add(sv.getQuery());
            booleanFilter.setValueList(Arrays.asList((Object) function));
        }
        this.filter = booleanFilter;
        if (in.isNot()) {
            booleanFilter.setIsNot(true);
        }
    }


    private boolean isDistinct(drds.plus.parser.abstract_syntax_tree.expression.primary.function.Function function) {
        if (function instanceof Max) {
            return ((Max) function).isDistinct();
        } else if (function instanceof Min) {
            return ((Min) function).isDistinct();
        } else if (function instanceof Sum) {
            return ((Sum) function).isDistinct();
        } else if (function instanceof Count) {
            return ((Count) function).isDistinct();
        } else if (function instanceof Avg) {
            return ((Avg) function).isDistinct();
        } else {
            return false;
        }
    }

    private Join join(ITable leftTable, ITable rightTable) {
        ExpressionVisitor lev = new ExpressionVisitor(parent);
        leftTable.accept(lev);
        Query leftNode = lev.getQuery();
        //
        ExpressionVisitor rev = new ExpressionVisitor(parent);
        rightTable.accept(rev);
        Query rightNode = rev.getQuery();
        //
        Join joinNode = leftNode.join(rightNode);
        return joinNode;
    }

    private void addJoinFilter(Join joinNode, Filter filter) {
        if (filter instanceof BooleanFilter) {
            joinNode.addJoinFilter((BooleanFilter) filter);
        } else if (filter instanceof LogicalOperationFilter) {
            LogicalOperationFilter logicalOperationFilter = (LogicalOperationFilter) filter;
            if (!logicalOperationFilter.getOperation().equals(Operation.and)) {
                // 比如出现 A.id = B.id And ( A.id = 1 or A.columnName = 3)这里的or条件可直接做为other join filter
                // 如果出现 A.id = B.id or A.columnName = B.columnName，那就是一个未知情况了
                joinNode.setOtherJoinOnFilter(logicalOperationFilter);
            } else {
                List<Filter> filterList = logicalOperationFilter.getFilterList();
                if (filterList != null) {
                    for (Filter $filter : filterList) {
                        addJoinFilter(joinNode, $filter);
                    }
                } else {
                    throw new IllegalStateException("and has no other columnNameList , " + filter);
                }
            }
        }
    }

    /**
     * get the whole expression string,include everything of this query
     */
    protected String getExpressionSqlString(Expression expression) {
        StringBuilder sb = new StringBuilder();
        VisitorImpl visitor = new VisitorImpl(sb);
        expression.accept(visitor);
        return sb.toString();
    }

    public Object getObject() {
        if (columnOrValue == null) {
            if (filter == null) {
                // 子查询也可以做为一个列
                // 比如
                // 1. id > ALL(subQuery)
                // 2. query (subQuery)
                // 3. query (subQuery) + 5 > 10
                Function function = ObjectCreateFactory.createFunction();
                function.setColumnName(expressionSqlString);
                function.setFunctionName(FunctionName.subquery_scalar);
                function.getArgList().add(query);
                columnOrValue = function;
                return columnOrValue;
            } else {
                return filter;
            }
        } else {
            return columnOrValue;
        }
    }

    public Comparable getValueForLike() {
        return valueForLike;
    }

    public Filter getFilter() {
        return filter;
    }

    public Query getQuery() {
        return query;
    }

    public String getExpressionSqlString() {
        return expressionSqlString;
    }

}
